How to execute an action on viewDidLoad of an UIViewController
private var onViewLoadContext: UInt8 = 0
public protocol UIViewControllerOnViewLoadProtocol { }
extension UIViewController: UIViewControllerOnViewLoadProtocol { }
private class OnViewControllerViewLoadObserver<T>: NSObject {
private var handlers: [(T) -> Void]
var token: NSKeyValueObservation?
init (_ handler: @escaping (T) -> Void) {
self.handlers = [handler]
}
func invoke(_ value: T) {
self.handlers.forEach { handler in
handler(value)
}
}
func add(handler: @escaping (T) -> Void) {
self.handlers.append(handler)
}
}
public extension UIViewControllerOnViewLoadProtocol where Self: UIViewController {
func addOnViewLoad(handler: @escaping (Self?) -> Void) {
let observer: OnViewControllerViewLoadObserver<Self?>
if let existingObserver = objc_getAssociatedObject(self, &onViewLoadContext) as? OnViewControllerViewLoadObserver<Self?> {
observer = existingObserver
observer.add(handler: handler)
} else {
observer = OnViewControllerViewLoadObserver(handler)
objc_setAssociatedObject(
self,
&onViewLoadContext,
observer,
objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC
)
observer.token = self.observe(\.view) { [weak observer, weak self] (_, _) in
observer?.invoke(self)
}
}
}
func removeOnViewLoad() {
objc_setAssociatedObject(
self,
&onViewLoadContext,
nil,
objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC
)
}
}